<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        canvas {
            margin: 100px 0 0 100px;
        }
    </style>
</head>

<body>
    <canvas width="200" height="200" style="border: 1px solid black;"></canvas>
    <script>
        //生成50个食物,有大小区别,
        //颜色,随机,
        function Bounds(ratio = 1) {
            // const width = 200
            // const height = 200
            const num = 50
            const types = [1, 2, 3, 4]
            let boundlists = []
            function randfn(len = 200, min = 0) {
                return Math.floor(Math.random() * len) + min
            }
            function color() {
                return `rgb(${randfn()},${randfn()},${randfn()})`
            }
            //获取食物数组
            function getbounds() {
                const x = randfn(199, 1)
                const y = randfn(199, 1)
                boundlists.push({ pos: [x, y], color: color(), type: [types[randfn(4)]] })
                if (boundlists.length < 50) {
                    getbounds()
                }
            }
            getbounds()
            return {
                randfn(len = 200, min = 0) {
                    return Math.floor(Math.random() * len) + min
                },
                color() {
                    return `rgb(${randfn()},${randfn()},${randfn()})`
                },
                getbounds() {
                    const x = randfn(199, 1)
                    const y = randfn(199, 1)
                    boundlists.push({ pos: [x, y], color: color(), type: [types[randfn(4)]] })
                    if (boundlists.length < 50) {
                        getbounds()
                    }
                    return boundlists
                }, boundlists
            }
        }

        //移动
        //改变方向
        function Snake(width = 200, height = 200) {
            //随机函数用于生成舌头的位置
            function randfn(len = Math.fround(width * 0.9), min = Math.fround(width * 0.1)) {
                return Math.floor(Math.random() * len) + min
            }

            //初始化蛇头,随机生成位置
            let snakelists = [[randfn(), randfn()]]
            //剩下的三个身体
            for (let i = 0; i < 3; i++) {
                snakelists.push([snakelists[i][0] + 1, snakelists[i][1]])
            }
            // //蛇的初始方向
            let direction
            // //判断方向键的合法性
            function getdirction(dir) {
                //获取前两节
                const [[x, y], [x1, y1]] = snakelists
                if (x + dir[0] === x1 && y + dir[1] === y1) return
                // console.log(dir);
                // console.log(x,y);
                // console.log(x1,y1);

                return direction = dir
            }
            // // console.log(snakelists);
            // //蛇的移动
            // function move() {
            //     let head = snakelists[0]
            //     let temparr = [[head[0] + direction[0], head[1] + direction[1]]]
            //     for (let i = 0; i < snakelists.length - 1; i++) {
            //         temparr.push(snakelists[i])
            //     }
            //     snakelists = temparr
            // }
            // //如果吃到了,蛇的长度
            // function eat() {
            //     let head = snakelists[0]
            //     let temparr = [[head[0] + direction[0], head[1] + direction[1]]]
            //     for (let i = 0; i < snakelists.length; i++) {
            //         temparr.push(snakelists[i])
            //     }
            //     snakelists = temparr
            // }
            return {
                //蛇的初始方向
                // console.log(snakelists);
                //蛇的移动
                move(direction) {
                    // debugger
                    let dir = getdirction(direction)
                    if (!dir) return snakelists
                    let head = snakelists[0]
                    let temparr = [[head[0] + dir[0], head[1] + dir[1]]]
                    for (let i = 0; i < snakelists.length - 1; i++) {
                        temparr.push(snakelists[i])
                    }
                    return snakelists = temparr
                },
                //如果吃到了,蛇的长度
                eat(direction) {
                    let dir = getdirction(direction)
                    let head = snakelists[0]
                    let temparr = [[head[0] + dir[0], head[1] + dir[1]]]
                    for (let i = 0; i < snakelists.length; i++) {
                        temparr.push(snakelists[i])
                    }
                    return snakelists = temparr
                }
                , snakelists
            }
        }
        Snake()
        function Game(ratio, width, height, frametime) {
            // 画板
            const canvas = document.querySelector("canvas");
            // 画笔
            const ctx = canvas.getContext("2d");
            // //倍率
            // const ratio = ratio
            // //宽
            // const width = width
            // //高
            // const height = height
            // //刷新频率
            // let frametime = frametime
            //分数
            let score = 0
            //生命
            let livies = 3
            //当前生命状态
            let state = true

            window.onclick =(()=>
            {
                if (!state) {
                startgame()
                }
            })


            //生成,蛇
            let snake = Snake()
            //生成食物
            const bounds = Bounds()

            let keep = [-1, 0]
            // let k =[-1,0]
            lastTime = 0
            window.onkeydown = (e) => {
                keyword(e.key)

                // keyword(e.key)
                keep = defult(e.key)    
                // console.log(keep);
            }
            //   window.requestAnimationFrame()
            // requestAnimationFrame(frame)
            triggle(keep)



            // setInterval(() => {
            //     triggle()
            //     // frame(frametime)
            // }, 100);

            //刷新帧
            // function frame(t) {
            //     triggle()
            //     requestAnimationFrame(frame)
            // }
            // let fram = frame(frametime)
            function frame(t) {
                if (lastTime === 0) {
                    lastTime = t
                } else if (t - lastTime > frametime) {
                    triggle()
                    lastTime = t
                }
                requestAnimationFrame(frame)
            }
            frame(frametime)
            // requestAnimationFrame(triggle.bind(this)) 
            //键盘事件
            function keyword(key) {
                // debugger
                switch (key) {
                    case 'ArrowUp':
                        triggle([0, -1])
                        break
                    case 'ArrowDown':
                        triggle([0, 1])
                        break
                    case 'ArrowLeft':
                        triggle([-1, 0])
                        break
                    case 'ArrowRight':
                        triggle([1, 0])
                        break
                }
            }
            function defult(key) {
                // debugger

                if (key === 'ArrowUp' || key === 'w') {
                    return [0, -1]
                }
                else if (key === 'ArrowDown' || key === 's') {
                    return [0, 1]
                } else if (key === 'ArrowLeft' || key === 'a') {
                    return [-1, 0]
                }
                else if (key === 'ArrowRight' || key === 'd') {
                    return [1, 0]
                }

            }

            //绘制基本元素
            //画蛇
            function drawsnake() {
                for (let item of snake.snakelists) {
                    // console.log(item);
                    // console.log(snake.snakelists[0]);
                    if (item === snake.snakelists[0])
                        ctx.fillStyle = '#90b'
                    else ctx.fillStyle = 'orange'
                    ctx.fillRect(item[0], item[1], 2, 2);
                }

            }
            //画食物
            function drawBound() {
                for (let item of bounds.boundlists) {
                    // console.log(item);
                    ctx.fillStyle = `${item.color}`
                    // console.log(item.pos[0],item.pos[1]);
                    ctx.fillRect(item.pos[0], item.pos[1], item.type[0], item.type[0]);
                }
            }
            //画图
            function draw() {
                ctx.clearRect(0, 0, canvas.width, canvas.height)
                drawBound()
                drawsnake()
                ctx.fillStyle = 'rgba(255,0,0,.4)'
                ctx.font = 40 * ratio + "px Georgia"
                const { width, actualBoundingBoxAscent, actualBoundingBoxDescent, } = ctx.measureText(score + '')
                const height = actualBoundingBoxAscent + actualBoundingBoxDescent
                ctx.fillText(score + '', (width * ratio - width) / 2, (height * ratio ) / 2)
            }


            //实时的渲染页面
            function triggle(key = keep) {
                // console.log(keep);
                if (!state) return over()
                // debugger
                let oldhead = snake.snakelists[0]
                let head = [[oldhead[0] + key[0], oldhead[1] + key[1]]]
                // draw()
                const [oldhaed, ...snkebody] = snake.snakelists
                //边界判定
                if (head[0][0] > width || head[0][0] <= 0 || head[0][1] > height || head[0][1] <= 0) over()

                //食物碰撞判定s
                for (let i = 0; i < bounds.boundlists.length; i++) {
                    let { pos, type } = bounds.boundlists[i]
                    //自身判定
                    for (let i = 1; i < snkebody.length - 1; i++) {
                        // debugger
                        if (head[0][0] === snkebody[i][0] && head[0][1] === snkebody[i][1]) over()
                    }


                    if ((head[0][0] >= pos[0] - 1 && head[0][0] <= pos[0] + type[0] - 1) && head[0][1] >= pos[1] - 1 && head[0][1] <= pos[1] + type[0] - 1) {
                        // console.log('head0, pos,typ = ' + head[0][0], pos[0], type[0]);
                        // console.log('head1, pos,typ = ' + head[0][1], pos[1], type[0]);
                        snake.snakelists = snake.eat(key)
                        bounds.boundlists.splice(i, 1)
                        bounds.boundlists = bounds.getbounds()
                        score += type[0]
                        // drawBound()
                        // drawsnake()
                        break
                    }
                }
                snake.snakelists = snake.move(key)

                draw()

            }


            //游戏结束
            function over() {
                if (state) {
                    livies--
                    if (!livies) alert(`游戏结束,您最后的得分是${score}`)

                    if (confirm(`您还有${livies}条命,目前得分为${score},
                

                是否继续游戏`)) {
                        startgame()
                    }
                }
                return state = false
            }
            //游戏开始
            function startgame() {
                state = true
                // let len = snake.snakelists
                snake = Snake()
                frame(frametime)
            }
        }
        Game(2, 200, 200, 40)

    </script>
</body>

</html>